package com.kkb.mybatis.config;

import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.Text;
import org.junit.Test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * User: zsl
 * Date: 2019/10/1018:39
 * Description: 创建sqlSource其实就是对select等crud标签中的sql脚本进行处理
 */
public class XMLScriptPaser {

    private  Configuration configuration;

    private  boolean isDynamic = false;

    private Map<String,NodeHandler> nodeHandlerMap = new HashMap<String, NodeHandler>();

    public XMLScriptPaser(Configuration configuration) {
        this.configuration = configuration;
        initNodeHandlerMap();
    }

    public void initNodeHandlerMap(){
        nodeHandlerMap.put("if",new IfNodeHandler());
    }

    public void parseSelect(Element element) {

    }

    public SqlSource parseScriptNode(Element selectElement) {
        //首先将sql 脚本按照不同的类型,封装到不同的 sqlnode
        MixedSqlNode rootSqlNode =  parseDynamicTags(selectElement);
        //再将 sqlnode 封装到 sqlDource 中
        SqlSource sqlSource = null;
        if(isDynamic){
            sqlSource = new DynamicSqlSource(rootSqlNode);
        } else {
            sqlSource = new RowSqlSource(rootSqlNode);
        }
        //由于带有 ${} 和 #{},动态标签的sql处理方式不同,所以需要封装到不同的sqlsource中

        return  sqlSource;
    }

    /**
     * 将 sql 封装到不同的 sqlnode 中
     * @param selectElement
     * @return
     */
    private MixedSqlNode parseDynamicTags(Element selectElement) {
        List<SqlNode>  contents = new ArrayList<SqlNode>();
        boolean isDynamic = false;
        int nodeCount = selectElement.nodeCount(); //获取select 里边的节点数量
        for (int i = 0; i < nodeCount; i++) {
            Node node = selectElement.node(i);
            //区分node节点的类型 是 text 还是 if 或者 where
            //如果是文本类型则封装到 textSqlNode 或者 StaticTextSqlNode
            if(node instanceof Text){
                String sqlText = node.getText().trim();
                if(sqlText == null || sqlText.equals("")){
                    continue;
                }
                TextSqlNode sqlNode = new TextSqlNode(sqlText);
                //判断 sqlText 中是否带有 ${}
                if(sqlNode.isSynamic(sqlText)){
                    contents.add(sqlNode);
                    isDynamic = true;
                } else {
                    contents.add(new StaticTextSqlNode(sqlText));
                }
            }else{  //如果不是文本方式,则调用递归解析
                //比如if where foreach等动态sql子标签 就在这进行解析
                //根据标签的不同,封装到不同的nodesql中去
                Element nodeToHandler =(Element)node;
                String nodeName = nodeToHandler.getName().toLowerCase();
                NodeHandler nodeHandler = nodeHandlerMap.get(nodeName);
                nodeHandler.handleNode(nodeToHandler,contents);

                isDynamic = true;
            }
        }
        return new MixedSqlNode(contents);
    }


    public class IfNodeHandler implements NodeHandler {

        public void handleNode(Element nodeToHandle, List<SqlNode> targetContents) {
            MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle);
            //对if标签进行解析
            String test = nodeToHandle.attributeValue("test");
            IfSqlNode ifSqlNode = new IfSqlNode(test,mixedSqlNode);
            targetContents.add(ifSqlNode);
        }
    }
}
